package it.cast.wechat.service.ServiceImpl;

import it.cast.wechat.dto.OrderItemVo;
import it.cast.wechat.dto.OrderVo;
import it.cast.wechat.dto.ProductVo;
import it.cast.wechat.mapper.ProductMapper;
import it.cast.wechat.pojo.Category;
import it.cast.wechat.pojo.Product;
import it.cast.wechat.pojo.ProductExample;
import it.cast.wechat.pojo.User;
import it.cast.wechat.service.CategoryService;
import it.cast.wechat.service.OrdersService;
import it.cast.wechat.service.ProductService;
import it.cast.wechat.service.UserService;
import it.cast.wechat.utils.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private UserService userService;

    @Autowired
    private OrdersService ordersService;


    @Override
    public int deleteProduct(String productId) {
        int state = productMapper.deleteByPrimaryKey(productId);
        return state;
    }

    @Override
    public Optional<Product> queryProduct(String productId) {
        Product product = productMapper.selectByPrimaryKey(productId);
        return Optional.ofNullable(product);
    }

    @Override
    public List<Product> queryProductByCategoryId(String categoryId) {
        ProductExample example = new ProductExample();
        ProductExample.Criteria criteria = example.createCriteria();
        criteria.andCategoryIdEqualTo(categoryId);

        List<Product> products = productMapper.selectByExample(example);
        return products;
    }

    @Override
    public int saveProduct(Product product) {
        int state = 0;
        if(StringUtils.isEmpty(product.getProductId())){
            product.setProductId(CommonUtils.uuid());
            product.setProductFlag(1);
            state = productMapper.insertSelective(product);
        }else {
            state = productMapper.updateByPrimaryKeySelective(product);
        }
        return state;
    }

    @Override
    public List<Product> queryAllProduct() {
        ProductExample example = new ProductExample();
        ProductExample.Criteria criteria = example.createCriteria();
        criteria.andProductIdIsNotNull();
        List<Product> products = productMapper.selectByExample(example);
        return products;
    }

    @Override
    public List<ProductVo> queryAllProductWithCategory() {
        List<Product> products = queryAllProduct();
        return products.stream().map(product -> {
            ProductVo productVo = product.builderProductVo();
            Category category = categoryService.queryCategoryById(product.getCategoryId());
            if(category != null){
                productVo.setCategory(category);
            }
            return productVo;
        }).collect(Collectors.toList());

    }

    //根据用户id，查找其订单下的所有商品id，不重复的
    private Set<String> getProductIdByUserId(String userId) {
        List<OrderVo> orderVos = ordersService.queryOrderByUserId(userId, null);
        Set<String> collect = orderVos.stream()
                .flatMap(orderVo -> {
                    List<OrderItemVo> orderItems = orderVo.getOrderItems();
                    return orderItems.stream();
                })
                .map(OrderItemVo::getProduct)
                .map(Product::getProductId)
                .collect(Collectors.toSet());
        return collect;
    }

    public List<Product> getRecommend(String id) {
        //存放所有用户数据
        Map<String, Map<String, Double>> allUsers = new HashMap<String, Map<String, Double>>();
        //查询所有的用户
        List<User> allUsers1 = userService.getAll();
        //查询所有的商品
        List<Product> allFilm = queryAllProduct();
        //循环遍历每一个用户
        for (User users : allUsers1) {
            //根据用户得到购买的商品以及数量
            List<OrderVo> orderByUserList = ordersService.queryOrderByUserId(users.getId(),null);
            if (orderByUserList.size() > 0) {
                Map<String, Double> u = new HashMap<String, Double>();//存放商品ID 购买数量
                for (OrderVo orders : orderByUserList) {
                    //获取订单中的每个商品的商品和id
                    orders.getOrderItems().stream()
                            .forEach(orderItemVo -> {
                                //先查询是否已有商品的id
                                String productId = orderItemVo.getProduct().getProductId();
                                Double num = u.get(productId);
                                if(num == null || num == 0.0){
                                    num = orderItemVo.getCount() * 1.0;
                                }else {
                                    num = num + orderItemVo.getCount() * 1.0;
                                }
                                u.put(productId, num);
                            });
                }
                //将该用户没有买过的商品置为0.0
                for (Product film : allFilm) {//循环每一个商品
                    String goodId = film.getProductId();//商品列表中的商品id
                    Double num = u.get(goodId);
                    if(num == null){
                        u.put(goodId, 0.0);
                    }
                }
                //存放每一个用户购买商品的信息
                allUsers.put(users.getId(), u);
            }
        }
        Map<String, Double> simUserSimMap = new HashMap<String, Double>();//存放相似度集合
        Map<String, Double> per = allUsers.get(id);//获取当前用户

        if(per == null || simUserSimMap == null){
            return allFilm;
        }
        //遍历每一个用户
        for (Map.Entry<String, Map<String, Double>> stringMapEntry : allUsers.entrySet()) {
            String perId = stringMapEntry.getKey();
            if (!id.equals(perId)) {
                double sim = CommonUtils.getUserSimilar(per, stringMapEntry.getValue());
                System.out.println("皮尔森公式=======" + sim);
                System.out.println(String.valueOf(sim));
                simUserSimMap.put(perId, sim);
            }
        }
        //获取相似度最高的用户，对simUserSimMap中的数据进行排序
        List<Map.Entry<String, Double>> wordMap = new ArrayList<>(simUserSimMap.entrySet());
        Collections.sort(wordMap, new Comparator<Map.Entry<String, Double>>() {// 根据value排序
            public int compare(Map.Entry<String, Double> o1, Map.Entry<String, Double> o2) {
                double result = o2.getValue() - o1.getValue();
                if (result > 0)
                    return 1;
                else if (result == 0)
                    return 0;
                else
                    return -1;
            }
        });
        //皮尔森系数大于0.6的用户id添加到集合中
        List<String> useridList = new ArrayList<>();
        for (Map.Entry<String, Double> set : wordMap) {
            if (set.getValue() >= 0.6) {
                useridList.add(set.getKey());
            }
            System.out.println("从大到小的顺序是map:" + set.getKey() + "   " + set.getValue());
        }

        List<String> filmsList = new ArrayList<>();
        //根据当前用户的id得到具体的商品
        Set<String> products = getProductIdByUserId(id);
        useridList.forEach(userId -> {
            Set<String> productUserIds = getProductIdByUserId(userId);
            productUserIds.removeAll(products);
            filmsList.addAll(productUserIds);
        });

        List<Product> productList = new ArrayList<>();
        if(CollectionUtils.isEmpty(filmsList)){
            filmsList.forEach(productId ->{
                Optional<Product> product = queryProduct(productId);
                productList.add(product.get());
            });
        }else {
            products.forEach(productId ->{
                Optional<Product> product = queryProduct(productId);
                productList.add(product.get());
            });
        }

        return productList;
    }


}
